package importExport;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.RenderingHints.Key;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.io.PrintStream;
import java.text.AttributedCharacterIterator;
import java.util.Map;
import java.util.Vector;

import org.w3c.dom.Element;

public class VSSGraphics2D extends Graphics2D{
	PrintStream p;
	AffineTransform transform;
	int cFillPat=-1;
	int cPenPat=-1;
	Color cColor=null;
	static String HANDLE="hd";
	static String HANDLE1="hd1";
	static String BOOLEAN="bl";
	// only drawShape
	// fillShape
	
	public VSSGraphics2D(PrintStream p){
		System.out.println("VSSGraphics contsructed");
		transform=new AffineTransform();
		this.p=p;
		
	}
	
	
	
	public void drawLine2D(Line2D line){
		drawLine2D(line.getP1(),line.getP2());
	}
	public void drawLine2D(Point2D p1,Point2D p2){
		doPenPat(1);
		doFillPat(0);
		p.print("moveTo(");
		p.print(p1.getX());
		p.print(",");
		p.print(p1.getY());
		p.println(");");
		
		p.print("lineTo(");
		p.print(p2.getX());
		p.print(",");
		p.print(p2.getY());
		p.println(");");
	}
	
	public void drawEllipse2D(Ellipse2D ellipse){
		p.print("oval(");
		p.print(""+ellipse.getMinX());
		p.print(",");
		p.print(""+ellipse.getMinY());
		p.print(",");
		p.print(""+ellipse.getMaxX());
		p.print(",");
		p.print(""+ellipse.getMaxY());
		p.println(");");
	}
	
	public void drawRectangle2D(Rectangle2D rectangle){
		p.print("rect(");
		p.print(""+rectangle.getMinX());
		p.print(",");
		p.print(""+rectangle.getMinY());
		p.print(",");
		p.print(""+rectangle.getMaxX());
		p.print(",");
		p.print(""+rectangle.getMaxY());
		p.println(");");
	}
	
	public void drawGeneralPathOld(GeneralPath path){
		// always close
		// no Holes;
		// straight lines;
		p.println("closePoly;");
		p.println("beginPoly;");
		
		//path.
		
		String points="";
		 float[] coords = new float[6];
		    for (PathIterator i = path.getPathIterator(null); !i.isDone(); i
		        .next()) {
		      int type = i.currentSegment(coords);
		      
		      switch (type) {
		      case PathIterator.SEG_CUBICTO:
		        break;
		      case PathIterator.SEG_QUADTO:
		    	  break;
		      case PathIterator.SEG_MOVETO:
		    	  p.println("addPoint("+coords[0]+","+coords[1]+");");
		    	  points+=coords[0]+","+coords[1];
		      case PathIterator.SEG_LINETO:
		    	  p.println("addPoint("+coords[0]+","+coords[1]+");");
		      case PathIterator.SEG_CLOSE:
		        break;
		      default:
		    	  break;
		      }
		    }
			p.println("endPoly;");
	}
	public void drawGeneralPath(Shape shape){
		
		Vector<Vector<Point2D>> contours=getVectorWithHoles(shape);
		drawPoly(contours);
	}
	
	public void drawPoly(Vector<Vector<Point2D>> contours){
		doPenPat(1);
		doFillPat(0);
		makePoly(contours);
	}
	
	public void fillPoly(Vector<Vector<Point2D>> contours){
		doPenPat(0);
		doFillPat(1);
		makePoly(contours);
	}
	
	public static double getArea(Vector<Point2D> points) {
		double area = 0;
		int j;
		for (int i = 0; i < points.size(); i++) {
			j = i + 1;
			if (j == points.size())
				j = 0;
			Point2D p1 = points.get(i);
			Point2D p2 = points.get(j);
			area += (p1.getX() + p2.getX()) * (p2.getY() - p1.getY());
		}
		return area / 2.;
	}

	private void makePoly(Vector<Vector<Point2D>> contours){
		// always close
		// straight lines;
		double maxArea=0;
		Vector<Point2D> outterRing=null;
		for (int i=0;i<contours.size();i++){
			Vector<Point2D> ring=contours.get(i);
			double cArea=Math.abs(getArea(ring));
			if (outterRing==null||cArea>maxArea) {
				outterRing=ring;
				maxArea=cArea;
			}
		}
		contours.remove(outterRing);
		p.println("closePoly;");
		
		makeRing(outterRing);
		this.printCommand(HANDLE+":=lNewObj;");
		Vector<Point2D>ring=null;
		for (int j=0;j<contours.size();j++){
			ring=contours.get(j);
			makeRing(ring);
			this.printCommand(HANDLE1+":=lNewObj;");
			this.printCommand(BOOLEAN+":=addHole("+HANDLE+","+HANDLE1+");");
			this.printCommand("DelObject("+HANDLE1+");");
		//this.printCommand(BOOLEAN+":=addHole("+HANDLE+",lNewObj);");
		}
		
	}
	public void drawRing(Vector<Point2D> ring){
		doPenPat(1);
		doFillPat(0);
		makeRing(ring);
	}
	public void fillRing(Vector<Point2D> ring){
		doPenPat(0);
		doFillPat(1);
		makeRing(ring);
	}
	private void makeRing(Vector<Point2D> ring){
		// always close
		// straight lines;
		
		p.println("closePoly;");
		p.println("beginPoly;");
		for (int i=0;i<ring.size();i++){
			Point2D pt=ring.get(i);
			p.println("addPoint("+pt.getX()+","+pt.getY()+");");
		}
		p.println("endPoly;");
	}
	
	
	@Override
	public void addRenderingHints(Map<?, ?> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void clip(Shape arg0) {
		// TODO Auto-generated method stub
		
	}

	public void doPenPat(int i){
		if (cPenPat!=i){
			cPenPat=i;
			p.println("PenPat("+cPenPat+");");
		}
	}
	public void doFillPat(int i){
		if (cFillPat!=i){
			cFillPat=i;
			p.println("FillPat("+cFillPat+");");
		}
	}
	@Override
	public void draw(Shape shape) {
		doPenPat(1);
		doFillPat(0);
		
		drawVWShape(shape);
	}

	@Override
	public void drawGlyphVector(GlyphVector arg0, float arg1, float arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean drawImage(Image arg0, AffineTransform arg1, ImageObserver arg2) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void drawImage(BufferedImage arg0, BufferedImageOp arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawRenderableImage(RenderableImage arg0, AffineTransform arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawRenderedImage(RenderedImage arg0, AffineTransform arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawString(String arg0, int arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawString(String arg0, float arg1, float arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawString(AttributedCharacterIterator arg0, int arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawString(AttributedCharacterIterator arg0, float arg1, float arg2) {
		// TODO Auto-generated method stub
		
	}

	public void drawVWShape(Shape shape){
		System.out.println("drawVWShape");
		Class cClass=shape.getClass();
		System.out.println(cClass);
		if (cClass.equals(Rectangle2D.Double.class)){
			this.drawRectangle2D((Rectangle2D) shape);
		}
		else if (cClass.equals(Ellipse2D.Double.class)){
			this.drawEllipse2D((Ellipse2D) shape);
		}
		else if (cClass.equals(Line2D.Double.class)){
			this.drawLine2D((Line2D) shape);
		}
		else if (cClass.equals(GeneralPath.class)){
			this.drawGeneralPath((GeneralPath) shape);
		}
		else if (cClass.equals(Area.class)){
			
			this.drawGeneralPath(shape);
		}
	}
	@Override
	public void fill(Shape shape) {
		System.out.println("fill");
		doPenPat(0);
		doFillPat(1);
		drawVWShape(shape);
	}

	
	
	@Override
	public Color getBackground() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Composite getComposite() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public GraphicsConfiguration getDeviceConfiguration() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public FontRenderContext getFontRenderContext() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Paint getPaint() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getRenderingHint(Key arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public RenderingHints getRenderingHints() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Stroke getStroke() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AffineTransform getTransform() {
		// TODO Auto-generated method stub
		return transform;
	}

	@Override
	public boolean hit(Rectangle arg0, Shape arg1, boolean arg2) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void rotate(double arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void rotate(double arg0, double arg1, double arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void scale(double arg0, double arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setBackground(Color arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setComposite(Composite arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setPaint(Paint arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setRenderingHint(Key arg0, Object arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setRenderingHints(Map<?, ?> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setStroke(Stroke stroke) {
		
		float w=((BasicStroke)stroke).getLineWidth();
		int cW=(int)(w*10.);
		p.println("PenSize("+cW+");");
	}

	@Override
	public void setTransform(AffineTransform arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void shear(double arg0, double arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void transform(AffineTransform arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void translate(int arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void translate(double arg0, double arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void clearRect(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void clipRect(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void copyArea(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Graphics create() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawArc(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean drawImage(Image arg0, int arg1, int arg2, ImageObserver arg3) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean drawImage(Image arg0, int arg1, int arg2, Color arg3, ImageObserver arg4) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, ImageObserver arg5) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, Color arg5, ImageObserver arg6) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, ImageObserver arg9) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, Color arg9, ImageObserver arg10) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void drawLine(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawOval(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawPolygon(int[] arg0, int[] arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawPolyline(int[] arg0, int[] arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drawRoundRect(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fillArc(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fillOval(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fillPolygon(int[] arg0, int[] arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fillRect(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fillRoundRect(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Shape getClip() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Rectangle getClipBounds() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Color getColor() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Font getFont() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public FontMetrics getFontMetrics(Font arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setClip(Shape arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setClip(int arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}
public int getIntVWColor(int c){
		return (int)(c*65535.0/255.);
	}
	

	@Override
	public void setColor(Color c) {
		if (!c.equals(cColor)){
		String colorString="";
		colorString+=""+getIntVWColor(c.getRed());
		colorString+=","+getIntVWColor(c.getGreen());
		colorString+=","+getIntVWColor(c.getBlue());
		// TODO Auto-generated method stub
		p.println("PenBack("+colorString+");");
		p.println("FillBack("+colorString+");");
		}
	}

	@Override
	public void setFont(Font arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setPaintMode() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setXORMode(Color arg0) {
		// TODO Auto-generated method stub
		
	}
	public void printCommand(String command){
		p.println(command);
	}
	
	public void beginGroup(){
		p.println("beginGroup;");
	}
	public void endGroup(){
		p.println("endGroup;");
	}
	
	public void beginSymbol(String name){
		p.println("BeginSym('"+name+"');");
	}
	public void endSymbol(){
		p.println("EndSym;");
	}
	public void beginExtrude(double bottom,double top){
		p.println("BeginXtrd("+bottom+","+top+");");
	}
	public void endExtrude(){
		p.println("EndXtrd;");
	}
	public void nameClass(String name){
		p.println("nameClass('"+name+"');");
	}
	public void layer(String name){
		p.println("Layer('"+name+"');");
	}
	
	public static Vector<Vector<Point2D>> getPoly(PathIterator pi) {
		Vector<Vector<Point2D>> allPoints = new Vector<Vector<Point2D>>();
		Vector<Point2D> points = new Vector<Point2D>();
		while (pi.isDone() == false) {
			double[] coordinates = new double[6];
			int type = pi.currentSegment(coordinates);

			switch (type) {
			case PathIterator.SEG_MOVETO:
				points = new Vector<Point2D>();
				points.add(new Point2D.Double(coordinates[0], coordinates[1]));
				break;
			case PathIterator.SEG_LINETO:
				Point2D.Double newP = new Point2D.Double(coordinates[0],
						coordinates[1]);
				if (!points.firstElement().equals(newP)) {
					points.add(newP);
				}
				break;

			case PathIterator.SEG_CLOSE:
				allPoints.add(points);
				break;
			default:
				break;
			}
			pi.next();

		}
		return allPoints;
	}

	public static Vector<Vector<Point2D>> getVectorWithHoles(Shape shape) {
		return getVectorWithHoles(shape.getPathIterator(null));
	}

	public static Vector<Vector<Point2D>> getVectorWithHoles(PathIterator pi) {
		return getPoly(pi);
	}
}
